bitkeeper revision 1.1159.170.45 (419cb897jRheBdVSsNm7oNbz_Q4DeQ)
authorbren@anvil.research <bren@anvil.research>
Thu, 18 Nov 2004 14:58:31 +0000 (14:58 +0000)
committerbren@anvil.research <bren@anvil.research>
Thu, 18 Nov 2004 14:58:31 +0000 (14:58 +0000)
Bring x2d2 to latest headers. Quite some fixes to make it compile.

.rootkeys
tools/x2d2/Makefile
tools/x2d2/cntrl_con.c
tools/x2d2/domain_controller.h [deleted file]
tools/x2d2/main.c [deleted file]
tools/x2d2/minixend.c [new file with mode: 0644]
tools/x2d2/minixend.h

index 3f63948f7af75510f884c6305cb039805c32ef9e..7f9a7fb994ece5ae2ca0dada7bb2d737dddf003f 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 40fcefb3zGC9XNBkSwTEobCoq8YClA tools/sv/inc/style.css
 4194e861IgTabTt8HOuh143QIJFD1Q tools/x2d2/Makefile
 4194e861M2gcBz4i94cQYpqzi8n6UA tools/x2d2/cntrl_con.c
-4194e861xToz-o2KH6VT_CPJqVGMCg tools/x2d2/domain_controller.h
-4194e8612TrrMvC8ZlA4h2ZYCPWz4g tools/x2d2/main.c
+4194e8612TrrMvC8ZlA4h2ZYCPWz4g tools/x2d2/minixend.c
 4194e861x2eqNCD61RYPCUEBVdMYuw tools/x2d2/minixend.h
 4194e861A4V9VbD_FYmgXpYEj5YwVg tools/x2d2/util.c
 403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
index e1337bffa51fbc27f5fdeac15490ef8ace85bd09..36de2856ae4c9e93e3d828fc2705de6bb178ab6e 100644 (file)
@@ -1,10 +1,22 @@
-CFLAGS+=-Wall -g -Werror
+XEN_ROOT=../..
+include $(XEN_ROOT)/tools/Make.defs
 
-SRCS=main.c cntrl_con.c util.c
+CC       = gcc
+CFLAGS   = -Wall -Werror -g
 
-all: minixend
+CFLAGS  += -I $(XEN_XC)
+CFLAGS  += -I $(XEN_LIBXC)
+CFLAGS  += -I $(XEN_LIBXUTIL)
 
-#$(SRCS): minixend.h
+HDRS     = $(wildcard *.h)
+OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
 
-minixend: $(subst .c,.o,$(SRCS))
-       gcc $^ -o $@ $(LDFLAGS) -lxc -lpthread
+BIN      = minixend
+
+all: $(BIN)
+
+clean:
+       $(RM) *.a *.so *.o *.rpm $(BIN)
+
+$(BIN): $(OBJS)
+       $(CC) $(CFLAGS) $^ -o $@ -L$(XEN_LIBXC) -L$(XEN_LIBXUTIL) -lxc -lxutil -lpthread
index 5851d7df387f6dd567daf8872b10c76a28a40c00..46084dbdee8d03de09b017a7fa1b9ccdbdac7a44 100644 (file)
@@ -40,7 +40,6 @@ domain_created(const char *name, int mem_kb, int domid)
 
        pthread_mutex_init(&d->mux, NULL);
        pthread_cond_init(&d->cond, NULL);
-
        pthread_create(&d->thread, NULL, domain_thread_func, d);
 
        list_insert_after(&d->domain_list, &head_domain);
@@ -164,7 +163,7 @@ create_command_handler(struct open_connection *oc, const struct command *ign,
                send_message(oc, "E01 failed to parse %s\n", args);
                return;
        }
-       r = xc_domain_create(xc_handle, mem_kb, name, -1, 0, &domid);
+       r = xc_domain_create(xc_handle, mem_kb, -1, 0, &domid);
        if (r < 0) {
                send_message(oc, "E02 creating domain (%s)\n",
                             strerror(errno));
@@ -377,8 +376,8 @@ destroy_command_handler(struct open_connection *oc,
 
        r = xc_domain_destroy(xc_handle, domid);
        if (r < 0) {
-               send_message(oc, "E19 error destroying domain %d: %s\n",
-                            domid, sys_errlist[errno]);
+               send_message( oc, "E19 error destroying domain %d: %s\n",
+                             domid, strerror(errno) );
                return;
        }
        d->state = DOM_STATE_DEAD;
diff --git a/tools/x2d2/domain_controller.h b/tools/x2d2/domain_controller.h
deleted file mode 100644 (file)
index 14775c0..0000000
+++ /dev/null
@@ -1,562 +0,0 @@
-/******************************************************************************
- * domain_controller.h
- * 
- * Interface to server controller (e.g., 'xend'). This header file defines the 
- * interface that is shared with guest OSes.
- * 
- * Copyright (c) 2004, K A Fraser
- */
-
-/* I've copied this from the xen source pool as getting Xen and
-   userspace headers to play nicely together is beyond me -- sos22 */
-#define PACKED __attribute__ ((packed))
-typedef unsigned long memory_t;   /* Full-sized pointer/address/memory-size. */
-#define __MEMORY_PADDING(_X) u32 __pad_ ## _X
-#define _MEMORY_PADDING(_X)  __MEMORY_PADDING(_X)
-#define MEMORY_PADDING       _MEMORY_PADDING(__LINE__)
-typedef u16 domid_t;
-
-/*
- * Reason codes for SCHEDOP_shutdown. These are opaque to Xen but may be
- * interpreted by control software to determine the appropriate action. These 
- * are only really advisories: the controller can actually do as it likes.
- */
-#define SHUTDOWN_poweroff   0  /* Domain exited normally. Clean up and kill. */
-#define SHUTDOWN_reboot     1  /* Clean up, kill, and then restart.          */
-#define SHUTDOWN_suspend    2  /* Clean up, save suspend info, kill.         */
-
-
-/*
- * CONTROLLER MESSAGING INTERFACE.
- */
-
-typedef struct {
-    u8 type;     /*  0: echoed in response */
-    u8 subtype;  /*  1: echoed in response */
-    u8 id;       /*  2: echoed in response */
-    u8 length;   /*  3: number of bytes in 'msg' */
-    u8 msg[60];  /*  4: type-specific message data */
-} PACKED control_msg_t; /* 64 bytes */
-
-#define CONTROL_RING_SIZE 8
-typedef u32 CONTROL_RING_IDX;
-#define MASK_CONTROL_IDX(_i) ((_i)&(CONTROL_RING_SIZE-1))
-
-typedef struct {
-    control_msg_t tx_ring[CONTROL_RING_SIZE];   /*    0: guest -> controller */
-    control_msg_t rx_ring[CONTROL_RING_SIZE];   /*  512: controller -> guest */
-    CONTROL_RING_IDX tx_req_prod, tx_resp_prod; /* 1024, 1028 */
-    CONTROL_RING_IDX rx_req_prod, rx_resp_prod; /* 1032, 1036 */
-} PACKED control_if_t; /* 1040 bytes */
-
-/*
- * Top-level command types.
- */
-#define CMSG_CONSOLE        0  /* Console                 */
-#define CMSG_BLKIF_BE       1  /* Block-device backend    */
-#define CMSG_BLKIF_FE       2  /* Block-device frontend   */
-#define CMSG_NETIF_BE       3  /* Network-device backend  */
-#define CMSG_NETIF_FE       4  /* Network-device frontend */
-#define CMSG_SHUTDOWN       6  /* Shutdown messages       */
-#define CMSG_PDB_BE         7  /* PDB backend.            */
-#define CMSG_PDB_FE         8  /* PDB frontend.           */
-
-/******************************************************************************
- * CONSOLE DEFINITIONS
- */
-
-/*
- * Subtypes for console messages.
- */
-#define CMSG_CONSOLE_DATA       0
-
-
-/******************************************************************************
- * BLOCK-INTERFACE FRONTEND DEFINITIONS
- */
-
-/* Messages from domain controller to guest. */
-#define CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED   0
-
-/* Messages from guest to domain controller. */
-#define CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED     32
-#define CMSG_BLKIF_FE_INTERFACE_CONNECT         33
-#define CMSG_BLKIF_FE_INTERFACE_DISCONNECT      34
-
-/* These are used by both front-end and back-end drivers. */
-#define blkif_vdev_t   u16
-#define blkif_pdev_t   u16
-#define blkif_sector_t u64
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_STATUS_CHANGED:
- *  Notify a guest about a status change on one of its block interfaces.
- *  If the interface is DESTROYED or DOWN then the interface is disconnected:
- *   1. The shared-memory frame is available for reuse.
- *   2. Any unacknowledged messgaes pending on the interface were dropped.
- */
-#define BLKIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
-#define BLKIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
-#define BLKIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
-typedef struct {
-    u32 handle; /*  0 */
-    u32 status; /*  4 */
-    u16 evtchn; /*  8: (only if status == BLKIF_INTERFACE_STATUS_CONNECTED). */
-} PACKED blkif_fe_interface_status_changed_t; /* 10 bytes */
-
-/*
- * CMSG_BLKIF_FE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the front-end driver is DOWN or UP.
- *  When the driver goes DOWN then the controller will send no more
- *  status-change notifications. When the driver comes UP then the controller
- *  will send a notification for each interface that currently exists.
- *  If the driver goes DOWN while interfaces are still UP, the domain
- *  will automatically take the interfaces DOWN.
- */
-#define BLKIF_DRIVER_STATUS_DOWN   0
-#define BLKIF_DRIVER_STATUS_UP     1
-typedef struct {
-    /* IN */
-    u32 status;        /*  0: BLKIF_DRIVER_STATUS_??? */
-    /* OUT */
-    /*
-     * Tells driver how many interfaces it should expect to immediately
-     * receive notifications about.
-     */
-    u32 nr_interfaces; /*  4 */
-} PACKED blkif_fe_driver_status_changed_t; /* 8 bytes */
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_CONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_CONNECTED message.
- */
-typedef struct {
-    u32      handle;      /*  0 */
-    u32      __pad;
-    memory_t shmem_frame; /*  8 */
-    MEMORY_PADDING;
-} PACKED blkif_fe_interface_connect_t; /* 16 bytes */
-
-/*
- * CMSG_BLKIF_FE_INTERFACE_DISCONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_DISCONNECTED message.
- */
-typedef struct {
-    u32 handle; /*  0 */
-} PACKED blkif_fe_interface_disconnect_t; /* 4 bytes */
-
-
-/******************************************************************************
- * BLOCK-INTERFACE BACKEND DEFINITIONS
- */
-
-/* Messages from domain controller. */
-#define CMSG_BLKIF_BE_CREATE      0  /* Create a new block-device interface. */
-#define CMSG_BLKIF_BE_DESTROY     1  /* Destroy a block-device interface.    */
-#define CMSG_BLKIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
-#define CMSG_BLKIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
-#define CMSG_BLKIF_BE_VBD_CREATE  4  /* Create a new VBD for an interface.   */
-#define CMSG_BLKIF_BE_VBD_DESTROY 5  /* Delete a VBD from an interface.      */
-#define CMSG_BLKIF_BE_VBD_GROW    6  /* Append an extent to a given VBD.     */
-#define CMSG_BLKIF_BE_VBD_SHRINK  7  /* Remove last extent from a given VBD. */
-
-/* Messages to domain controller. */
-#define CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED 32
-
-/*
- * Message request/response definitions for block-device messages.
- */
-
-typedef struct {
-    blkif_sector_t sector_start;   /*  0 */
-    blkif_sector_t sector_length;  /*  8 */
-    blkif_pdev_t   device;         /* 16 */
-    u16            __pad;          /* 18 */
-} PACKED blkif_extent_t; /* 20 bytes */
-
-/* Non-specific 'okay' return. */
-#define BLKIF_BE_STATUS_OKAY                0
-/* Non-specific 'error' return. */
-#define BLKIF_BE_STATUS_ERROR               1
-/* The following are specific error returns. */
-#define BLKIF_BE_STATUS_INTERFACE_EXISTS    2
-#define BLKIF_BE_STATUS_INTERFACE_NOT_FOUND 3
-#define BLKIF_BE_STATUS_INTERFACE_CONNECTED 4
-#define BLKIF_BE_STATUS_VBD_EXISTS          5
-#define BLKIF_BE_STATUS_VBD_NOT_FOUND       6
-#define BLKIF_BE_STATUS_OUT_OF_MEMORY       7
-#define BLKIF_BE_STATUS_EXTENT_NOT_FOUND    8
-#define BLKIF_BE_STATUS_MAPPING_ERROR       9
-
-/* This macro can be used to create an array of descriptive error strings. */
-#define BLKIF_BE_STATUS_ERRORS {    \
-    "Okay",                         \
-    "Non-specific error",           \
-    "Interface already exists",     \
-    "Interface not found",          \
-    "Interface is still connected", \
-    "VBD already exists",           \
-    "VBD not found",                \
-    "Out of memory",                \
-    "Extent not found for VBD",     \
-    "Could not map domain memory" }
-
-/*
- * CMSG_BLKIF_BE_CREATE:
- *  When the driver sends a successful response then the interface is fully
- *  created. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u16        __pad;
-    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED blkif_be_create_t; /* 12 bytes */
-
-/*
- * CMSG_BLKIF_BE_DESTROY:
- *  When the driver sends a successful response then the interface is fully
- *  torn down. The controller will send a DESTROYED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify interface to be destroyed. */
-    u16        __pad;
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED blkif_be_destroy_t; /* 12 bytes */
-
-/*
- * CMSG_BLKIF_BE_CONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  connected. The controller will send a CONNECTED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u16        __pad;
-    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
-    memory_t   shmem_frame;   /*  8: Page cont. shared comms window.     */
-    MEMORY_PADDING;
-    u32        evtchn;        /* 16: Event channel for notifications.    */
-    /* OUT */
-    u32        status;        /* 20 */
-} PACKED blkif_be_connect_t;  /* 24 bytes */
-
-/*
- * CMSG_BLKIF_BE_DISCONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  disconnected. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u16        __pad;
-    u32        blkif_handle;  /*  4: Domain-specific interface handle.   */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED blkif_be_disconnect_t; /* 12 bytes */
-
-/* CMSG_BLKIF_BE_VBD_CREATE */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u16        __pad;
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_vdev_t vdevice;     /*  8: Interface-specific id for this VBD. */
-    u16        readonly;      /* 10: Non-zero -> VBD isn't writable.     */
-    /* OUT */
-    u32        status;        /* 12 */
-} PACKED blkif_be_vbd_create_t; /* 16 bytes */
-
-/* CMSG_BLKIF_BE_VBD_DESTROY */
-typedef struct {
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u16        __pad0;        /*  2 */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
-    u16        __pad1;        /* 10 */
-    /* OUT */
-    u32        status;        /* 12 */
-} PACKED blkif_be_vbd_destroy_t; /* 16 bytes */
-
-/* CMSG_BLKIF_BE_VBD_GROW */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u16        __pad0;        /*  2 */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_extent_t extent;    /*  8: Physical extent to append to VBD.   */
-    blkif_vdev_t vdevice;     /* 28: Interface-specific id of the VBD.   */
-    u16        __pad1;        /* 30 */
-    /* OUT */
-    u32        status;        /* 32 */
-} PACKED blkif_be_vbd_grow_t; /* 36 bytes */
-
-/* CMSG_BLKIF_BE_VBD_SHRINK */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify blkdev interface.          */
-    u16        __pad0;        /*  2 */
-    u32        blkif_handle;  /*  4: ...ditto...                         */
-    blkif_vdev_t vdevice;     /*  8: Interface-specific id of the VBD.   */
-    u16        __pad1;        /* 10 */
-    /* OUT */
-    u32        status;        /* 12 */
-} PACKED blkif_be_vbd_shrink_t; /* 16 bytes */
-
-/*
- * CMSG_BLKIF_BE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the back-end driver is DOWN or UP.
- *  If the driver goes DOWN while interfaces are still UP, the controller
- *  will automatically send DOWN notifications.
- */
-typedef struct {
-    u32        status;        /*  0: BLKIF_DRIVER_STATUS_??? */
-} PACKED blkif_be_driver_status_changed_t; /* 4 bytes */
-
-
-/******************************************************************************
- * NETWORK-INTERFACE FRONTEND DEFINITIONS
- */
-
-/* Messages from domain controller to guest. */
-#define CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED   0
-
-/* Messages from guest to domain controller. */
-#define CMSG_NETIF_FE_DRIVER_STATUS_CHANGED     32
-#define CMSG_NETIF_FE_INTERFACE_CONNECT         33
-#define CMSG_NETIF_FE_INTERFACE_DISCONNECT      34
-
-/*
- * CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED:
- *  Notify a guest about a status change on one of its network interfaces.
- *  If the interface is DESTROYED or DOWN then the interface is disconnected:
- *   1. The shared-memory frame is available for reuse.
- *   2. Any unacknowledged messgaes pending on the interface were dropped.
- */
-#define NETIF_INTERFACE_STATUS_DESTROYED    0 /* Interface doesn't exist.    */
-#define NETIF_INTERFACE_STATUS_DISCONNECTED 1 /* Exists but is disconnected. */
-#define NETIF_INTERFACE_STATUS_CONNECTED    2 /* Exists and is connected.    */
-typedef struct {
-    u32        handle; /*  0 */
-    u32        status; /*  4 */
-    u16        evtchn; /*  8: status == NETIF_INTERFACE_STATUS_CONNECTED */
-    u8         mac[6]; /* 10: status == NETIF_INTERFACE_STATUS_CONNECTED */
-} PACKED netif_fe_interface_status_changed_t; /* 16 bytes */
-
-/*
- * CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the front-end driver is DOWN or UP.
- *  When the driver goes DOWN then the controller will send no more
- *  status-change notifications. When the driver comes UP then the controller
- *  will send a notification for each interface that currently exists.
- *  If the driver goes DOWN while interfaces are still UP, the domain
- *  will automatically take the interfaces DOWN.
- */
-#define NETIF_DRIVER_STATUS_DOWN   0
-#define NETIF_DRIVER_STATUS_UP     1
-typedef struct {
-    /* IN */
-    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
-    /* OUT */
-    /*
-     * Tells driver how many interfaces it should expect to immediately
-     * receive notifications about.
-     */
-    u32        nr_interfaces; /*  4 */
-} PACKED netif_fe_driver_status_changed_t; /* 8 bytes */
-
-/*
- * CMSG_NETIF_FE_INTERFACE_CONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_CONNECTED message.
- */
-typedef struct {
-    u32        handle;         /*  0 */
-    u32        __pad;          /*  4 */
-    memory_t   tx_shmem_frame; /*  8 */
-    MEMORY_PADDING;
-    memory_t   rx_shmem_frame; /* 16 */
-    MEMORY_PADDING;
-} PACKED netif_fe_interface_connect_t; /* 24 bytes */
-
-/*
- * CMSG_NETIF_FE_INTERFACE_DISCONNECT:
- *  If successful, the domain controller will acknowledge with a
- *  STATUS_DISCONNECTED message.
- */
-typedef struct {
-    u32        handle;        /*  0 */
-} PACKED netif_fe_interface_disconnect_t; /* 4 bytes */
-
-
-/******************************************************************************
- * NETWORK-INTERFACE BACKEND DEFINITIONS
- */
-
-/* Messages from domain controller. */
-#define CMSG_NETIF_BE_CREATE      0  /* Create a new net-device interface. */
-#define CMSG_NETIF_BE_DESTROY     1  /* Destroy a net-device interface.    */
-#define CMSG_NETIF_BE_CONNECT     2  /* Connect i/f to remote driver.        */
-#define CMSG_NETIF_BE_DISCONNECT  3  /* Disconnect i/f from remote driver.   */
-
-/* Messages to domain controller. */
-#define CMSG_NETIF_BE_DRIVER_STATUS_CHANGED 32
-
-/*
- * Message request/response definitions for net-device messages.
- */
-
-/* Non-specific 'okay' return. */
-#define NETIF_BE_STATUS_OKAY                0
-/* Non-specific 'error' return. */
-#define NETIF_BE_STATUS_ERROR               1
-/* The following are specific error returns. */
-#define NETIF_BE_STATUS_INTERFACE_EXISTS    2
-#define NETIF_BE_STATUS_INTERFACE_NOT_FOUND 3
-#define NETIF_BE_STATUS_INTERFACE_CONNECTED 4
-#define NETIF_BE_STATUS_OUT_OF_MEMORY       5
-#define NETIF_BE_STATUS_MAPPING_ERROR       6
-
-/* This macro can be used to create an array of descriptive error strings. */
-#define NETIF_BE_STATUS_ERRORS {    \
-    "Okay",                         \
-    "Non-specific error",           \
-    "Interface already exists",     \
-    "Interface not found",          \
-    "Interface is still connected", \
-    "Out of memory",                \
-    "Could not map domain memory" }
-
-/*
- * CMSG_NETIF_BE_CREATE:
- *  When the driver sends a successful response then the interface is fully
- *  created. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u16        __pad0;        /*  2 */
-    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
-    u8         mac[6];        /*  8 */
-    u16        __pad1;        /* 14 */
-    /* OUT */
-    u32        status;        /* 16 */
-} PACKED netif_be_create_t; /* 20 bytes */
-
-/*
- * CMSG_NETIF_BE_DESTROY:
- *  When the driver sends a successful response then the interface is fully
- *  torn down. The controller will send a DESTROYED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Identify interface to be destroyed. */
-    u16        __pad;
-    u32        netif_handle;  /*  4: ...ditto...                         */
-    /* OUT */
-    u32   status;             /*  8 */
-} PACKED netif_be_destroy_t; /* 12 bytes */
-
-/*
- * CMSG_NETIF_BE_CONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  connected. The controller will send a CONNECTED notification to the
- *  front-end driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;          /*  0: Domain attached to new interface.   */
-    u16        __pad0;         /*  2 */
-    u32        netif_handle;   /*  4: Domain-specific interface handle.   */
-    memory_t   tx_shmem_frame; /*  8: Page cont. tx shared comms window.  */
-    MEMORY_PADDING;
-    memory_t   rx_shmem_frame; /* 16: Page cont. rx shared comms window.  */
-    MEMORY_PADDING;
-    u16        evtchn;         /* 24: Event channel for notifications.    */
-    u16        __pad1;         /* 26 */
-    /* OUT */
-    u32        status;         /* 28 */
-} PACKED netif_be_connect_t; /* 32 bytes */
-
-/*
- * CMSG_NETIF_BE_DISCONNECT:
- *  When the driver sends a successful response then the interface is fully
- *  disconnected. The controller will send a DOWN notification to the front-end
- *  driver.
- */
-typedef struct { 
-    /* IN */
-    domid_t    domid;         /*  0: Domain attached to new interface.   */
-    u16        __pad;
-    u32        netif_handle;  /*  4: Domain-specific interface handle.   */
-    /* OUT */
-    u32        status;        /*  8 */
-} PACKED netif_be_disconnect_t; /* 12 bytes */
-
-/*
- * CMSG_NETIF_BE_DRIVER_STATUS_CHANGED:
- *  Notify the domain controller that the back-end driver is DOWN or UP.
- *  If the driver goes DOWN while interfaces are still UP, the domain
- *  will automatically send DOWN notifications.
- */
-typedef struct {
-    u32        status;        /*  0: NETIF_DRIVER_STATUS_??? */
-} PACKED netif_be_driver_status_changed_t; /* 4 bytes */
-
-
-/******************************************************************************
- * SHUTDOWN DEFINITIONS
- */
-
-/*
- * Subtypes for shutdown messages.
- */
-#define CMSG_SHUTDOWN_POWEROFF  0   /* Clean shutdown (SHUTDOWN_poweroff).   */
-#define CMSG_SHUTDOWN_REBOOT    1   /* Clean shutdown (SHUTDOWN_reboot).     */
-#define CMSG_SHUTDOWN_SUSPEND   2   /* Create suspend info, then             */
-                                    /* SHUTDOWN_suspend.                     */
-
-/******************************************************************************
- * PDB DEFINITIONS
- */
-
-/* Notify the backend that a new frontend has connected. */
-#define CMSG_PDB_BE_INTERFACE_CONNECTED 0
-typedef struct {
-    int assist_port;
-    int event_port;
-} pdb_be_connected_t;
-
-/* Notify the domain controller that the status of the backend has
-   changed. */
-#define CMSG_PDB_BE_DRIVER_STATUS_CHANGED 1
-typedef struct {
-    unsigned status;
-#define PDB_DRIVER_STATUS_UP 1
-    unsigned long event_page;
-    unsigned long assist_page;
-} pdb_be_driver_status_changed_t;
-
-/* Notify a front end that a back end just popped up. */
-#define CMSG_PDB_FE_NEW_BE 0
-typedef struct {
-    int domain;
-    int assist_evtchn;
-    int event_evtchn;
-    unsigned long assist_frame;
-    unsigned long event_frame;
-} pdb_fe_new_be_t;
diff --git a/tools/x2d2/main.c b/tools/x2d2/main.c
deleted file mode 100644 (file)
index c8de6b6..0000000
+++ /dev/null
@@ -1,1015 +0,0 @@
-#define _GNU_SOURCE
-
-#include <sys/types.h>
-#include <sys/fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/mman.h>
-#include <sys/select.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-#include <asm/page.h>
-#include <assert.h>
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <netinet/in.h>
-#include <printf.h>
-#include <pthread.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "minixend.h"
-
-#define NETWORK_SCRIPT "/etc/xen/scripts/network"
-#define VIFBRIDGE_SCRIPT "/etc/xen/scripts/vif-bridge"
-
-#define MINIXEND_PORT 5123
-
-#define mb() asm volatile ("" ::: "memory")
-
-static void send_control_message(int type, int subtype, int id,
-                                int size, void *payload,
-                                struct domain *target);
-
-struct list_head
-head_domain = LIST_HEAD(&head_domain);
-
-static struct list_head
-head_connection = LIST_HEAD(&head_connection);
-
-struct list_head
-head_console = LIST_HEAD(&head_console);
-
-#define foreach_open_connection(d)                                          \
-foreach_item(d, &head_connection, struct open_connection, connection_list)
-
-/* Not modified after initial start up */
-static struct domain *
-dom0;
-unsigned
-xc_handle;
-static int
-listen_fd;
-int
-evtchn_fd;
-
-static struct list_head
-head_event_receiver = LIST_HEAD(&head_event_receiver);
-
-struct event_receiver {
-       struct list_head list;
-       int id;
-       pthread_cond_t cond;
-};
-
-/* We're protected by the dom0 mutex in here */
-static struct event_receiver *
-allocate_event_receiver(struct domain *d)
-{
-       static int next_message_id;
-       struct event_receiver *work;
-
-       assert(d == dom0);
-       work = xmalloc(sizeof(*work));
-       work->id = next_message_id++;
-       pthread_cond_init(&work->cond, NULL);
-
-       list_insert_after(&work->list, &head_event_receiver);
-
-       return work;
-}
-
-static struct event_receiver *
-find_event_receiver(int id)
-{
-       struct event_receiver *work;
-       foreach_item(work, &head_event_receiver, struct event_receiver, list)
-               if (work->id == id)
-                       return work;
-       return NULL;
-}
-
-static void
-release_event_receiver(struct event_receiver *w)
-{
-       list_remove(&w->list);
-       pthread_cond_destroy(&w->cond);
-       free(w);
-}
-
-/* Send a message to dom0, and then block awaiting a reply. */
-/* Make sure we don't hold any domain mutexs */
-static void
-send_dom0_message_block(control_msg_t *msg)
-{
-       CONTROL_RING_IDX c;
-       struct event_receiver *er;
-       control_msg_t buf;
-
-       PRINTF(0, "sending message to dom0 and blocking for reply.\n");
-       pthread_mutex_lock(&dom0->mux);
-       PRINTF(0, "got dom0 lock.\n");
-       er = allocate_event_receiver(dom0);
-       PRINTF(0, "allocated evetn receiver.\n");
-       msg->id = er->id;
-       PRINTF(1, "sending message with id %d\n", msg->id);
-       send_control_message(msg->type, msg->subtype,
-                            msg->id, msg->length, msg->msg, dom0);
-       xc_evtchn_send(xc_handle, dom0->control_evtchn);
-
-       PRINTF(0, "waiting for reply\n");
-       pthread_cond_wait(&er->cond, &dom0->mux);
-       PRINTF(0, "got reply\n");
-
-       c = dom0->rx_resp_cons % CONTROL_RING_SIZE;
-       memcpy(&buf, &dom0->ctrl_if->rx_ring[c], sizeof(buf));
-       assert(msg->id == buf.id);
-       assert(msg->type == buf.type);
-       assert(msg->subtype == buf.subtype);
-       memcpy(msg, &buf, sizeof(*msg));
-       dom0->rx_resp_cons++;
-
-       release_event_receiver(er);
-
-       pthread_mutex_unlock(&dom0->mux);
-
-       PRINTF(1, "got reply to message with id %d\n", msg->id);
-}
-
-/* Allocate an interdomain event channel.  event_ports[0] is the
-   local event port number, event_ports[1] the remote */
-int
-allocate_event_channel(struct domain *d, int event_ports[2])
-{
-       return xc_evtchn_bind_interdomain(xc_handle, DOMID_SELF,
-                                         d->domid, event_ports,
-                                         event_ports+1);
-}
-
-static void
-accept_new_connection(void)
-{
-       int fd;
-       struct open_connection *oc;
-
-       fd = accept(listen_fd, NULL, NULL);
-       if (fd < 0)
-               return;
-       oc = xmalloc(sizeof(*oc));
-       oc->fd = fd;
-       oc->state = OC_STATE_CONNECTED;
-       oc->buf_used = 0;
-       oc->buf_allocated = 16;
-       oc->buf = xmalloc(oc->buf_allocated);
-       list_insert_after(&oc->connection_list, &head_connection);
-}
-
-static void
-closedown_connection(struct open_connection *oc)
-{
-       close(oc->fd);
-       assert(oc->buf);
-       free(oc->buf);
-       free(oc);
-}
-
-#if 0
-/* Hackl for the benefit of domain replay */
-static unsigned
-report_work(u32 *ptr, u32 val, unsigned dom, int do_direct)
-{
-       if (!do_direct) {
-               int rc;
-               asm("int $0x80" : "=a" (rc)
-                   : "0" (264), "b" (ptr), "c" (val), "d" (dom));
-               if (rc < 0) {
-                       errno = -rc;
-                       rc = -1;
-               }
-               return rc;
-       } else {
-               *ptr = val;
-               return 0;
-       }
-}
-#else
-static unsigned
-report_work(u32 *ptr, u32 val, unsigned dom, int do_direct)
-{
-       *ptr = val;
-       return 0;
-}
-#endif
-
-static void
-send_control_reply(const control_msg_t *msg, struct domain *d)
-{
-       CONTROL_RING_IDX c;
-
-       PRINTF(3,"Control reply, type %d:%d, length %d.\n",
-              msg->type, msg->subtype, msg->length);
-       c = d->ctrl_if->tx_resp_prod % CONTROL_RING_SIZE;
-       memcpy(&d->ctrl_if->tx_ring[c], msg, sizeof(*msg));
-       report_work(&d->ctrl_if->tx_resp_prod,
-                   d->ctrl_if->tx_resp_prod + 1,
-                   d->domid,
-                   0);
-       PRINTF(4,"tx_resp_prod %ld.\n", d->ctrl_if->tx_resp_prod);
-       assert(!d->plugged);
-}
-
-static void
-send_trivial_control_reply(const control_msg_t *msg, struct domain *d)
-{
-       control_msg_t rep;
-
-       memset(&rep, 0, sizeof(rep));
-       rep.type = msg->type;
-       rep.subtype = msg->subtype;
-       rep.id = msg->id;
-       send_control_reply(&rep, d);
-}
-
-static void
-process_console_control_message(control_msg_t *m, struct domain *d)
-{
-       int off;
-       int r;
-
-       if (m->subtype != CMSG_CONSOLE_DATA) {
-               warnx("unknown console message subtype %d",
-                     m->subtype);
-               return;
-       }
-
-       if (m->length > 60) {
-               warnx("truncating message from domain %d (was length %d)",
-                     d->domid, m->length);
-               m->length = 60;
-       }
-       PRINTF(1, "DOM%d: %.*s\n", d->domid, m->length, m->msg);
-       send_trivial_control_reply(m, d);
-
-       if (d->cc) {
-               PRINTF(5, "Have a console connection.\n");
-               if (d->cc->state == CC_STATE_CONNECTED) {
-                       PRINTF(5, "Console is connected, sending directly.\n");
-                       for (off = 0; off < m->length; off += r) {
-                               r = write(d->cc->fd, m->msg + off,
-                                         m->length - off);
-                               if (r <= 0) {
-                                       d->cc->state = CC_STATE_ERROR;
-                                       break;
-                               }
-                       }
-               } else {
-                       PRINTF(5, "Console not connected, buffering.\n");
-                       if (d->cc->buf_allocated == 0) {
-                               d->cc->buf_allocated = 60;
-                               d->cc->buf = xmalloc(d->cc->buf_allocated);
-                               d->cc->buf_used = 0;
-                       } else if (d->cc->buf_allocated <
-                                  d->cc->buf_used + m->length) {
-                               d->cc->buf_allocated += 60;
-                               d->cc->buf = xrealloc(d->cc->buf,
-                                                     d->cc->buf_allocated);
-                       }
-                       assert(d->cc->buf_allocated >=
-                              d->cc->buf_used + m->length);
-                       memcpy(d->cc->buf + d->cc->buf_used,
-                              m->msg,
-                              m->length);
-                       d->cc->buf_used += m->length;
-               }
-       }
-}
-
-static void
-process_blkif_fe_message(control_msg_t *m, struct domain *d)
-{
-       switch (m->subtype) {
-       default:
-               warnx("unknown blkif front end message subtype %d",
-                     m->subtype);
-       }
-}
-
-static void
-send_control_message(int type, int subtype, int id,
-                    int size, void *payload, struct domain *target)
-{
-       control_msg_t msg;
-       CONTROL_RING_IDX c;
-
-       msg.type = type;
-       msg.subtype = subtype;
-       msg.id = id;
-       msg.length = size;
-       memcpy(msg.msg, payload, size);
-
-       c = target->ctrl_if->rx_req_prod % CONTROL_RING_SIZE;
-       memcpy(&target->ctrl_if->rx_ring[c], &msg, sizeof(msg));
-       report_work(&target->ctrl_if->rx_req_prod,
-                   target->ctrl_if->rx_req_prod + 1,
-                   target->domid,
-                   0);
-       assert(!target->plugged);
-}
-
-/* Procedure for bringing a new netif front end up:
-
-   -- Front end sends us NETIF_FE_DRIVER_STATUS_CHANGED
-   -- We send back end NETIF_BE_CREATE, wait for a reply
-   -- Back end creates a new netif for us, replies
-   -- We send front end a NETIF_FE_DRIVER_STATUS_CHANGED message saying
-      how many interfaces we've created for it
-   -- We send front end a NETIF_FE_INTERFACE_STATUS_CHANGED for each
-      netif created
-   -- Front end sends us a NETIF_FE_INTERFACE_CONNECT for each netif
-*/
-static void
-handle_netif_fe_driver_status_changed(control_msg_t *m,
-                                     netif_fe_driver_status_changed_t *sh,
-                                     struct domain *d)
-{
-       netif_fe_interface_status_changed_t if_s;
-       control_msg_t be_msg;
-       netif_be_create_t *be = (void *)be_msg.msg;
-       int r;
-
-       switch (sh->status) {
-       case NETIF_DRIVER_STATUS_UP:
-               /* Tell the back end about the new interface coming
-                * up. */
-               if (d->created_netif_backend) {
-                       PRINTF(10, "Front end came up twice in dom %d -> reporting no interfaces this time around.\n", d->domid);
-                       sh->nr_interfaces = 0;
-                       send_control_reply(m, d);
-                       send_control_message(CMSG_NETIF_FE,
-                                            CMSG_NETIF_FE_DRIVER_STATUS_CHANGED,
-                                            1,
-                                            sizeof(*sh),
-                                            sh,
-                                            d);
-                       return;
-               }
-               be_msg.type = CMSG_NETIF_BE;
-               be_msg.subtype = CMSG_NETIF_BE_CREATE;
-               be_msg.id = d->domid;
-               be_msg.length = sizeof(*be);
-               be->domid = d->domid;
-               be->netif_handle = 0;
-               memcpy(be->mac, d->netif_mac, 6);
-
-               PRINTF(2,"Telling back end about new front end.\n");
-               pthread_mutex_unlock(&d->mux);
-               send_dom0_message_block(&be_msg);
-               pthread_mutex_lock(&d->mux);
-               PRINTF(3,"Done.\n");
-
-               if (be->status != NETIF_BE_STATUS_OKAY) {
-                       /* Uh oh... can't bring back end
-                        * up. */
-                       sh->nr_interfaces = 0;
-                       send_control_reply(m, d);
-                       send_control_message(CMSG_NETIF_FE,
-                                            CMSG_NETIF_FE_DRIVER_STATUS_CHANGED,
-                                            1,
-                                            sizeof(*sh),
-                                            sh,
-                                            d);
-                       return;
-               }
-               d->created_netif_backend = 1;
-
-               r = our_system(VIFBRIDGE_SCRIPT " up domain=%s mac=%.02x:%.02x:%.02x:%.02x:%.02x:%.02x vif=vif%d.0 bridge=xen-br0",
-                              d->name,
-                              d->netif_mac[0],
-                              d->netif_mac[1],
-                              d->netif_mac[2],
-                              d->netif_mac[3],
-                              d->netif_mac[4],
-                              d->netif_mac[5],
-                              d->domid);
-               if (r != 0)
-                       warn("error %d running " VIFBRIDGE_SCRIPT, r);
-
-               /* Tell domain how many interfaces it has to deal
-                * with. */
-               sh->nr_interfaces = 1;
-               send_control_reply(m, d);
-               send_control_message(CMSG_NETIF_FE,
-                                    CMSG_NETIF_FE_DRIVER_STATUS_CHANGED,
-                                    1,
-                                    sizeof(*sh),
-                                    sh,
-                                    d);
-
-               PRINTF(2,"Telling front end about its interfaces.\n");
-               if_s.handle = 0;
-               if_s.status = NETIF_INTERFACE_STATUS_DISCONNECTED;
-               send_control_message(CMSG_NETIF_FE,
-                                    CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED,
-                                    1,
-                                    sizeof(if_s),
-                                    &if_s,
-                                    d);
-               PRINTF(3,"Done.\n");
-
-               break;
-       default:
-               warnx("unknown netif status %ld", sh->status);
-               break;
-       }
-}
-
-static void
-handle_netif_fe_interface_connect(control_msg_t *m,
-                                 netif_fe_interface_connect_t *ic,
-                                 struct domain *d)
-{
-       control_msg_t be_msg;
-       netif_be_connect_t *bmsg = (void *)be_msg.msg;
-       netif_fe_interface_status_changed_t fmsg = {0};
-       int evtchn_ports[2];
-       int r;
-
-       PRINTF(4, "front end sent us an interface connect message.\n");
-       send_trivial_control_reply(m, d);
-
-       r = xc_evtchn_bind_interdomain(xc_handle,
-                                      dom0->domid,
-                                      d->domid,
-                                      &evtchn_ports[0],
-                                      &evtchn_ports[1]);
-       if (r < 0)
-               err(1, "allocating network event channel");
-
-       be_msg.type = CMSG_NETIF_BE;
-       be_msg.subtype = CMSG_NETIF_BE_CONNECT;
-       be_msg.id = 0;
-       be_msg.length = sizeof(*bmsg);
-       bmsg->domid = d->domid;
-       bmsg->netif_handle = ic->handle;
-       bmsg->tx_shmem_frame = ic->tx_shmem_frame;
-       bmsg->rx_shmem_frame = ic->rx_shmem_frame;
-       bmsg->evtchn = evtchn_ports[0];
-
-       pthread_mutex_unlock(&d->mux);
-       send_dom0_message_block(&be_msg);
-       pthread_mutex_lock(&d->mux);
-
-       if (bmsg->status != NETIF_BE_STATUS_OKAY) {
-               PRINTF(2, "error connected backend netif: %ld\n",
-                      bmsg->status);
-               abort(); /* Need to handle this */
-       } else {
-               PRINTF(3, "connect backend netif\n");
-
-               /* Tell the domain that we've connected it up. */
-               fmsg.handle = ic->handle;
-               fmsg.status = NETIF_INTERFACE_STATUS_CONNECTED;
-               fmsg.evtchn = evtchn_ports[1];
-               memcpy(fmsg.mac, d->netif_mac, 6);
-
-               send_control_message(CMSG_NETIF_FE,
-                                    CMSG_NETIF_FE_INTERFACE_STATUS_CHANGED,
-                                    0,
-                                    sizeof(fmsg),
-                                    &fmsg,
-                                    d);
-       }
-}
-
-static void
-process_netif_fe_message(control_msg_t *m, struct domain *d)
-{
-       switch (m->subtype) {
-       case CMSG_NETIF_FE_DRIVER_STATUS_CHANGED:
-       {
-               netif_fe_driver_status_changed_t *sh =
-                       (netif_fe_driver_status_changed_t *)m->msg;
-               handle_netif_fe_driver_status_changed(m, sh, d);
-               break;
-       }
-       case CMSG_NETIF_FE_INTERFACE_CONNECT:
-       {
-               netif_fe_interface_connect_t *ic =
-                       (netif_fe_interface_connect_t *)m->msg;
-               handle_netif_fe_interface_connect(m, ic, d);
-               break;
-       }
-       default:
-               warnx("unknown netif front end message subtype %d",
-                     m->subtype);
-       }
-}
-
-static void
-process_pdb_be_driver_status_changed_message(control_msg_t *msg,
-                                            pdb_be_driver_status_changed_t*pe,
-                                            struct domain *d)
-{
-       pdb_be_connected_t conn;
-       pdb_fe_new_be_t new_be;
-       int assist_channel[2];
-       int event_channel[2];
-       int r;
-
-       switch (pe->status) {
-       case PDB_DRIVER_STATUS_UP:
-               PRINTF(4, "creating event channel for PDB device\n");
-               r = allocate_event_channel(d, assist_channel);
-               r |= allocate_event_channel(d, event_channel);
-               if (r < 0)
-                       abort(); /* XXX need to handle this */
-
-               send_trivial_control_reply(msg, d);
-
-               PRINTF(4, "informing front end of event channel\n");
-               conn.assist_port = assist_channel[1];
-               conn.event_port = event_channel[1];
-               send_control_message(CMSG_PDB_BE,
-                                    CMSG_PDB_BE_INTERFACE_CONNECTED,
-                                    0,
-                                    sizeof(conn),
-                                    &conn,
-                                    d);
-
-               PRINTF(4, "informing back end of front end\n");
-               new_be.domain = d->domid;
-               new_be.assist_evtchn = assist_channel[0];
-               new_be.event_evtchn = event_channel[0];
-               new_be.assist_frame = pe->assist_page;
-               new_be.event_frame = pe->event_page;
-               send_control_message(CMSG_PDB_FE,
-                                    CMSG_PDB_FE_NEW_BE,
-                                    0,
-                                    sizeof(new_be),
-                                    &new_be,
-                                    dom0);
-               break;
-       default:
-               warnx("unknown pdb status %d", pe->status);
-       }
-}
-
-static void
-process_pdb_be_message(control_msg_t *msg, struct domain *d)
-{
-       switch (msg->subtype) {
-       case CMSG_PDB_BE_DRIVER_STATUS_CHANGED:
-       {
-               pdb_be_driver_status_changed_t *pe =
-                       (pdb_be_driver_status_changed_t *)msg->msg;
-               process_pdb_be_driver_status_changed_message(msg, pe, d);
-               break;
-       }
-       default:
-               warnx("unknown pdb back end message subtype %d",
-                     msg->subtype);
-       }
-}
-
-static void
-process_control_message(control_msg_t *msg, struct domain *d)
-{
-       control_msg_t m;
-
-       /* Don't want a malicous domain messing us about, so copy the
-          control mesasge into a local buffer. */
-       memcpy(&m, msg, sizeof(m));
-       switch (m.type) {
-       case CMSG_CONSOLE:
-               process_console_control_message(&m, d);
-               break;
-       case CMSG_BLKIF_FE:
-               process_blkif_fe_message(&m, d);
-               break;
-       case CMSG_NETIF_FE:
-               process_netif_fe_message(&m, d);
-               break;
-       case CMSG_PDB_BE:
-               process_pdb_be_message(&m, d);
-               break;
-       default:
-               warnx("unknown control message type %d", m.type);
-       }
-}
-
-static void
-domain_did_control_event(struct domain *d)
-{
-       CONTROL_RING_IDX c;
-
-       /* Pick up and process control ring messages. */
-       while (d->tx_req_cons != d->ctrl_if->tx_req_prod) {
-               c = d->tx_req_cons % CONTROL_RING_SIZE;
-               process_control_message(&d->ctrl_if->tx_ring[c], d);
-               d->tx_req_cons++;
-               assert(d->tx_req_cons <= d->ctrl_if->tx_req_prod);
-               PRINTF(5, "req_cons %ld, req_prod %ld.\n",
-                      d->tx_req_cons, d->ctrl_if->tx_req_prod);
-       }
-
-       /* Take any replies off, and discard them. */
-       if (d->rx_resp_cons != d->ctrl_if->rx_resp_prod)
-               PRINTF(1, "discard %ld events\n",
-                      d->ctrl_if->rx_resp_prod -
-                      d->rx_resp_cons);
-       d->rx_resp_cons = d->ctrl_if->rx_resp_prod;
-}
-
-/* This is the main function for domain control threads */
-void *
-domain_thread_func(void *D)
-{
-       struct domain *d = D;
-       int r;
-       CONTROL_RING_IDX old_resp_prod, old_req_prod;
-
-       pthread_mutex_lock(&d->mux);
-       for (;;) {
-               pthread_cond_wait(&d->cond, &d->mux);
-
-               old_resp_prod = d->ctrl_if->tx_resp_prod;
-               old_req_prod = d->ctrl_if->rx_req_prod;
-
-               domain_did_control_event(d);
-               if (d->cc && d->cc->in_buf_used != 0 && d->plugged == 0) {
-                       r = d->cc->in_buf_used;
-                       if (r > 60)
-                               r = 60;
-                       PRINTF(1, "Sending to domain: %.*s\n",
-                              r, d->cc->in_buf);
-                       send_control_message(CMSG_CONSOLE,
-                                            CMSG_CONSOLE_DATA,
-                                            0,
-                                            r,
-                                            d->cc->in_buf,
-                                            d);
-                       memmove(d->cc->in_buf, d->cc->in_buf + r,
-                               d->cc->in_buf_used - r);
-                       d->cc->in_buf_used -= r;
-               }
-
-               if (d->ctrl_if->tx_resp_prod != old_resp_prod ||
-                   d->ctrl_if->rx_req_prod != old_req_prod)
-                       xc_evtchn_send(xc_handle, d->control_evtchn);
-       }
-}
-
-/* This is the only thing you can do with a domain structure if you're
-   not in the thread which controls that domain.  Domain 0 is
-   special. */
-void
-signal_domain(struct domain *d)
-{
-       CONTROL_RING_IDX c;
-       int id;
-       struct event_receiver *evt;
-
-       pthread_mutex_lock(&d->mux);
-       if (d == dom0) {
-               /* Take events off of dom0's control ring, and send
-                  them to the event receivers. */
-               while (d->tx_req_cons != d->ctrl_if->tx_req_prod) {
-                       c = d->tx_req_cons % CONTROL_RING_SIZE;
-                       id = d->ctrl_if->tx_ring[c].id;
-                       evt = find_event_receiver(id);
-                       if (evt != NULL) {
-                               PRINTF(1, "delivering event id %d\n", evt->id);
-                               pthread_cond_broadcast(&evt->cond);
-                               pthread_mutex_unlock(&d->mux);
-                               pthread_yield();
-                               pthread_mutex_lock(&d->mux);
-                       } else {
-                               warnx("unexpected message id %d discarded",
-                                     id);
-                               d->tx_req_cons++;
-                       }
-               }
-               while (d->rx_resp_cons != d->ctrl_if->rx_resp_prod) {
-                       c = d->rx_resp_cons % CONTROL_RING_SIZE;
-                       id = d->ctrl_if->rx_ring[c].id;
-                       evt = find_event_receiver(id);
-                       if (evt != NULL) {
-                               PRINTF(1, "delivering event rep id %d\n", evt->id);
-                               pthread_cond_broadcast(&evt->cond);
-                               pthread_mutex_unlock(&d->mux);
-                               pthread_yield();
-                               pthread_mutex_lock(&d->mux);
-                       } else {
-                               warnx("unexpected message reply id %d discarded",
-                                     id);
-                               d->rx_resp_cons++;
-                       }
-               }
-       } else {
-               if (d->plugged) {
-                       d->event_pending = 1;
-               } else {
-                       pthread_cond_broadcast(&d->cond);
-               }
-       }
-       pthread_mutex_unlock(&d->mux);
-}
-
-static void
-handle_evtchn_event(void)
-{
-       short port;
-       struct domain *d;
-
-       read(evtchn_fd, &port, sizeof(short));
-       write(evtchn_fd, &port, sizeof(short));
-       foreach_domain (d) {
-               if (d->control_evtchn == port) {
-                       signal_domain(d);
-                       return;
-               }
-       }
-       warnx("got an event on an unknown port %d", port);
-}
-
-void *
-map_domain_mem(struct domain *d, unsigned long mfn)
-{
-       return xc_map_foreign_range(xc_handle, d->domid,
-                                   PAGE_SIZE, PROT_READ | PROT_WRITE,
-                                   mfn);
-}
-
-static void
-handle_console_event(struct console_connection *cc)
-{
-       int r;
-       int fd;
-
-       switch (cc->state) {
-       case CC_STATE_ERROR:
-               /* Errors shouldn't get here. */
-               abort();
-       case CC_STATE_PENDING:
-               fd = accept(cc->fd, NULL, NULL);
-               if (fd >= 0) {
-                       PRINTF(3, "Accepted console connection for domain %d",
-                              cc->dom->domid);
-                       close(cc->fd);
-                       cc->fd = fd;
-                       cc->state = CC_STATE_CONNECTED;
-                       while (cc->buf_used != 0) {
-                               r = write(cc->fd,
-                                         cc->buf,
-                                         cc->buf_used);
-                               if (r <= 0) {
-                                       cc->state = CC_STATE_ERROR;
-                                       break;
-                               }
-                               memmove(cc->buf,
-                                       cc->buf + r,
-                                       cc->buf_used - r);
-                               cc->buf_used -= r;
-                       }
-                       free(cc->buf);
-                       cc->buf = NULL;
-                       cc->buf_allocated = 0;
-               } else {
-                       PRINTF(1, "error %s accepting console", strerror(errno));
-               }
-               pthread_mutex_unlock(&cc->dom->mux);
-               break;
-       case CC_STATE_CONNECTED:
-               if (cc->in_buf_allocated == 0) {
-                       assert(cc->in_buf_used == 0);
-                       cc->in_buf_allocated = 128;
-                       cc->in_buf = xmalloc(cc->in_buf_allocated);
-               }
-               if (cc->in_buf_used == cc->in_buf_allocated) {
-                       cc->in_buf_allocated *= 2;
-                       cc->in_buf = xrealloc(cc->in_buf, cc->in_buf_allocated);
-               }
-               r = read(cc->fd, cc->in_buf + cc->in_buf_used,
-                        cc->in_buf_allocated - cc->in_buf_used);
-               if (r <= 0) {
-                       cc->state = CC_STATE_ERROR;
-               } else {
-                       cc->in_buf_used += r;
-               }
-               pthread_mutex_unlock(&cc->dom->mux);
-               signal_domain(cc->dom);
-               break;
-       }
-}
-
-static void
-handle_connection_event(struct open_connection *oc)
-{
-       int r;
-
-       /* We know that some amount of data is ready and waiting for
-          us.  Slurp it in. */
-       if (oc->buf_used == oc->buf_allocated) {
-               oc->buf_allocated *= 2;
-               oc->buf = xrealloc(oc->buf, oc->buf_allocated);
-       }
-       r = read(oc->fd, oc->buf + oc->buf_used,
-                oc->buf_allocated - oc->buf_used);
-       if (r < 0) {
-               warn("reading command from remote");
-               oc->state = OC_STATE_ERROR;
-       } else if (r == 0) {
-               warnx("reading command from remote");
-               oc->state = OC_STATE_ERROR;
-       } else {
-               oc->buf_used += r;
-               if (strchr(oc->buf, '\n'))
-                       oc->state = OC_STATE_COMMAND_PENDING;
-       }
-}
-
-static void
-get_and_process_event(void)
-{
-       fd_set read_fds, except_fds;
-       struct open_connection *oc;
-       struct console_connection *cc;
-       int max_fd = listen_fd;
-       int r;
-       struct list_head *li, *temp_li;
-
-       FD_ZERO(&read_fds);
-       FD_ZERO(&except_fds);
-       FD_SET(listen_fd, &read_fds);
-       FD_SET(evtchn_fd, &read_fds);
-       if (evtchn_fd > max_fd)
-               max_fd = evtchn_fd;
-       foreach_open_connection(oc) {
-               FD_SET(oc->fd, &read_fds);
-               FD_SET(oc->fd, &except_fds);
-               if (oc->fd > max_fd)
-                       max_fd = oc->fd;
-       }
-       foreach_console_connection(cc) {
-               FD_SET(cc->fd, &read_fds);
-               FD_SET(cc->fd, &except_fds);
-               if (cc->fd > max_fd)
-                       max_fd = cc->fd;
-       }
-
-       r = select(max_fd + 1, &read_fds, NULL, &except_fds, NULL);
-       if (r < 0)
-               err(1, "select");
-       if (FD_ISSET(listen_fd, &read_fds)) {
-               accept_new_connection();
-       } else if (FD_ISSET(evtchn_fd, &read_fds))
-               handle_evtchn_event();
-
-
-       foreach_open_connection(oc) {
-               if (FD_ISSET(oc->fd, &read_fds))
-                       handle_connection_event(oc);
-               if (FD_ISSET(oc->fd, &except_fds))
-                       oc->state = OC_STATE_ERROR;
-       }
-       list_foreach_safe(&head_console, li, temp_li) {
-               cc = list_item(li, struct console_connection, list);
-               if (FD_ISSET(cc->fd, &read_fds))
-                       handle_console_event(cc);
-               if (FD_ISSET(cc->fd, &except_fds) ||
-                   cc->state == CC_STATE_ERROR) {
-                       PRINTF(1, "Cleaning up console connection");
-                       cc->dom->cc = NULL;
-                       list_remove(&cc->list);
-                       close(cc->fd);
-                       if (cc->buf_allocated != 0)
-                               free(cc->buf);
-                       if (cc->in_buf_allocated != 0)
-                               free(cc->in_buf);
-                       free(cc);
-               }
-       }
-
-       /* Run pending stuff on the open connections. */
-       list_foreach_safe(&head_connection, li, temp_li) {
-               oc = list_item(li, struct open_connection, connection_list);
-               switch (oc->state) {
-               case OC_STATE_ERROR:
-                       list_remove(&oc->connection_list);
-                       closedown_connection(oc);
-                       break;
-               case OC_STATE_COMMAND_PENDING:
-                       process_command(oc);
-                       break;
-               case OC_STATE_CONNECTED:
-                       /* Don't need to do anything */
-                       break;
-               }
-       }
-}
-
-static int
-start_listening(void)
-{
-       int sock;
-       struct sockaddr_in inaddr;
-
-       sock = socket(PF_INET, SOCK_STREAM, 0);
-       if (sock < 0)
-               err(1, "creating socket");
-       memset(&inaddr, 0, sizeof(inaddr));
-       inaddr.sin_family = AF_INET;
-       inaddr.sin_port = htons(MINIXEND_PORT);
-
-       if (bind(sock, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0)
-               err(1, "binding to port %d", MINIXEND_PORT);
-       if (listen(sock, 5) < 0)
-               err(1, "listening for connections");
-
-       return sock;
-}
-
-static struct domain *
-find_dom0(void)
-{
-       int r;
-       xc_dominfo_t info;
-       struct domain *work;
-
-       r = xc_domain_getinfo(xc_handle, 0, 1, &info);
-       if (r < 0)
-               err(1, "getting domain 0 information");
-       work = xmalloc(sizeof(*work));
-       work->control_evtchn = 2;
-       if (ioctl(evtchn_fd, EVTCHN_BIND, 2) < 0)
-               err(1, "binding to domain 0 control event channel");
-
-       work->domid = 0;
-       work->name = xstrdup("dom0");
-       work->mem_kb = info.max_memkb;
-       work->state = DOM_STATE_RUNNING;
-       work->shared_info_mfn = info.shared_info_frame;
-
-       work->shared_info = map_domain_mem(work, info.shared_info_frame);
-       work->ctrl_if = (control_if_t *)((unsigned)work->shared_info + 2048);
-       work->tx_req_cons = work->ctrl_if->tx_req_prod;
-       work->rx_resp_cons = work->ctrl_if->rx_resp_prod;
-
-       pthread_mutex_init(&work->mux, NULL);
-       pthread_cond_init(&work->cond, NULL);
-
-       list_insert_after(&work->domain_list, &head_domain);
-
-       return work;
-}
-
-int
-main(int argc, char *argv[])
-{
-       int r;
-
-       r = our_system(NETWORK_SCRIPT " start antispoof=no");
-       if (r < 0)
-               err(1, "running " NETWORK_SCRIPT);
-       if (!WIFEXITED(r)) {
-               if (WIFSIGNALED(r)) {
-                       errx(1, NETWORK_SCRIPT " killed by signal %d",
-                            WTERMSIG(r));
-               }
-               errx(1, NETWORK_SCRIPT " terminated abnormally");
-       }
-       if (WEXITSTATUS(r) != 0)
-               errx(1, NETWORK_SCRIPT " returned error status %d",
-                    WEXITSTATUS(r));
-
-       xc_handle = xc_interface_open();
-
-       listen_fd = start_listening();
-
-       evtchn_fd = open("/dev/xen/evtchn", O_RDWR);
-       if (evtchn_fd < 0)
-               err(1, "openning /dev/xen/evtchn");
-
-       dom0 = find_dom0();
-
-       while (1) {
-               get_and_process_event();
-
-               PRINTF(5, "Dom0 ring state:\n");
-               PRINTF(5, "RX: req_prod %ld, resp_prod %ld, resp_cons %ld\n",
-                      dom0->ctrl_if->rx_req_prod,
-                      dom0->ctrl_if->rx_resp_prod,
-                      dom0->rx_resp_cons);
-               PRINTF(5, "TX: req_prod %ld, resp_prod %ld, req_cons %ld\n",
-                      dom0->ctrl_if->tx_req_prod,
-                      dom0->ctrl_if->tx_resp_prod,
-                      dom0->tx_req_cons);
-       }
-
-       return 0;
-}
-
diff --git a/tools/x2d2/minixend.c b/tools/x2d2/minixend.c
new file mode 100644 (file)
index 0000000..64fe271
--- /dev/null
@@ -0,0 +1,939 @@
+#define _GNU_SOURCE
+
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <asm/page.h>
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <printf.h>
+#include <pthread.h>
+#include <sched.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "minixend.h"
+
+#define NETWORK_SCRIPT "/etc/xen/scripts/network"
+#define VIFBRIDGE_SCRIPT "/etc/xen/scripts/vif-bridge"
+
+#define MINIXEND_PORT 5123
+
+#define mb() asm volatile ("" ::: "memory")
+
+static void send_control_message(int type, int subtype, int id,
+                                int size, void *payload,
+                                struct domain *target);
+
+struct list_head
+head_domain = LIST_HEAD(&head_domain);
+
+static struct list_head
+head_connection = LIST_HEAD(&head_connection);
+
+struct list_head
+head_console = LIST_HEAD(&head_console);
+
+#define foreach_open_connection(d)                                          \
+foreach_item(d, &head_connection, struct open_connection, connection_list)
+
+/* Not modified after initial start up */
+static struct domain *dom0;
+unsigned xc_handle;
+static int listen_fd;
+int evtchn_fd;
+
+static struct list_head
+head_event_receiver = LIST_HEAD(&head_event_receiver);
+
+struct event_receiver {
+       struct list_head list;
+       int id;
+       pthread_cond_t cond;
+};
+
+/* We're protected by the dom0 mutex in here */
+static struct event_receiver *
+allocate_event_receiver(struct domain *d)
+{
+       static int next_message_id;
+       struct event_receiver *work;
+
+       assert(d == dom0);
+       work = xmalloc(sizeof(*work));
+       work->id = next_message_id++;
+       pthread_cond_init(&work->cond, NULL);
+
+       list_insert_after(&work->list, &head_event_receiver);
+
+       return work;
+}
+
+static struct event_receiver *
+find_event_receiver(int id)
+{
+       struct event_receiver *work;
+       foreach_item(work, &head_event_receiver, struct event_receiver, list)
+               if (work->id == id)
+                       return work;
+       return NULL;
+}
+
+static void
+release_event_receiver(struct event_receiver *w)
+{
+       list_remove(&w->list);
+       pthread_cond_destroy(&w->cond);
+       free(w);
+}
+
+/* Send a message to dom0, and then block awaiting a reply. */
+/* Make sure we don't hold any domain mutexs */
+static void
+send_dom0_message_block(control_msg_t *msg)
+{
+       CONTROL_RING_IDX c;
+       struct event_receiver *er;
+       control_msg_t buf;
+
+       PRINTF(0, "sending message to dom0 and blocking for reply.\n");
+       pthread_mutex_lock(&dom0->mux);
+       PRINTF(0, "got dom0 lock.\n");
+       er = allocate_event_receiver(dom0);
+       PRINTF(0, "allocated evetn receiver.\n");
+       msg->id = er->id;
+       PRINTF(1, "sending message with id %d\n", msg->id);
+       send_control_message(msg->type, msg->subtype,
+                            msg->id, msg->length, msg->msg, dom0);
+       xc_evtchn_send(xc_handle, dom0->control_evtchn);
+
+       PRINTF(0, "waiting for reply\n");
+       pthread_cond_wait(&er->cond, &dom0->mux);
+       PRINTF(0, "got reply\n");
+
+       c = dom0->rx_resp_cons % CONTROL_RING_SIZE;
+       memcpy(&buf, &dom0->ctrl_if->rx_ring[c], sizeof(buf));
+       assert(msg->id == buf.id);
+       assert(msg->type == buf.type);
+       assert(msg->subtype == buf.subtype);
+       memcpy(msg, &buf, sizeof(*msg));
+       dom0->rx_resp_cons++;
+
+       release_event_receiver(er);
+
+       pthread_mutex_unlock(&dom0->mux);
+
+       PRINTF(1, "got reply to message with id %d\n", msg->id);
+}
+
+/* Allocate an interdomain event channel.  event_ports[0] is the
+   local event port number, event_ports[1] the remote */
+int
+allocate_event_channel(struct domain *d, int event_ports[2])
+{
+       return xc_evtchn_bind_interdomain(xc_handle, DOMID_SELF,
+                                         d->domid, event_ports,
+                                         event_ports+1);
+}
+
+static void
+accept_new_connection(void)
+{
+       int fd;
+       struct open_connection *oc;
+
+       fd = accept(listen_fd, NULL, NULL);
+       if (fd < 0)
+               return;
+       oc = xmalloc(sizeof(*oc));
+       oc->fd = fd;
+       oc->state = OC_STATE_CONNECTED;
+       oc->buf_used = 0;
+       oc->buf_allocated = 16;
+       oc->buf = xmalloc(oc->buf_allocated);
+       list_insert_after(&oc->connection_list, &head_connection);
+}
+
+static void
+closedown_connection(struct open_connection *oc)
+{
+       close(oc->fd);
+       assert(oc->buf);
+       free(oc->buf);
+       free(oc);
+}
+
+#if 0
+/* Hackl for the benefit of domain replay */
+static unsigned
+report_work(u32 *ptr, u32 val, unsigned dom, int do_direct)
+{
+       if (!do_direct) {
+               int rc;
+               asm("int $0x80" : "=a" (rc)
+                   : "0" (264), "b" (ptr), "c" (val), "d" (dom));
+               if (rc < 0) {
+                       errno = -rc;
+                       rc = -1;
+               }
+               return rc;
+       } else {
+               *ptr = val;
+               return 0;
+       }
+}
+#else
+static unsigned
+report_work(u32 *ptr, u32 val, unsigned dom, int do_direct)
+{
+       *ptr = val;
+       return 0;
+}
+#endif
+
+static void
+send_control_reply(const control_msg_t *msg, struct domain *d)
+{
+       CONTROL_RING_IDX c;
+
+       PRINTF(3,"Control reply, type %d:%d, length %d.\n",
+              msg->type, msg->subtype, msg->length);
+       c = d->ctrl_if->tx_resp_prod % CONTROL_RING_SIZE;
+       memcpy(&d->ctrl_if->tx_ring[c], msg, sizeof(*msg));
+       report_work(&d->ctrl_if->tx_resp_prod,
+                   d->ctrl_if->tx_resp_prod + 1,
+                   d->domid,
+                   0);
+       PRINTF(4,"tx_resp_prod %ld.\n", d->ctrl_if->tx_resp_prod);
+       assert(!d->plugged);
+}
+
+static void
+send_trivial_control_reply(const control_msg_t *msg, struct domain *d)
+{
+       control_msg_t rep;
+
+       memset(&rep, 0, sizeof(rep));
+       rep.type = msg->type;
+       rep.subtype = msg->subtype;
+       rep.id = msg->id;
+       send_control_reply(&rep, d);
+}
+
+static void
+process_console_control_message(control_msg_t *m, struct domain *d)
+{
+       int off;
+       int r;
+
+       if (m->subtype != CMSG_CONSOLE_DATA) {
+               warnx("unknown console message subtype %d",
+                     m->subtype);
+               return;
+       }
+
+       if (m->length > 60) {
+               warnx("truncating message from domain %d (was length %d)",
+                     d->domid, m->length);
+               m->length = 60;
+       }
+       PRINTF(1, "DOM%d: %.*s\n", d->domid, m->length, m->msg);
+       send_trivial_control_reply(m, d);
+
+       if (d->cc) {
+               PRINTF(5, "Have a console connection.\n");
+               if (d->cc->state == CC_STATE_CONNECTED) {
+                       PRINTF(5, "Console is connected, sending directly.\n");
+                       for (off = 0; off < m->length; off += r) {
+                               r = write(d->cc->fd, m->msg + off,
+                                         m->length - off);
+                               if (r <= 0) {
+                                       d->cc->state = CC_STATE_ERROR;
+                                       break;
+                               }
+                       }
+               } else {
+                       PRINTF(5, "Console not connected, buffering.\n");
+                       if (d->cc->buf_allocated == 0) {
+                               d->cc->buf_allocated = 60;
+                               d->cc->buf = xmalloc(d->cc->buf_allocated);
+                               d->cc->buf_used = 0;
+                       } else if (d->cc->buf_allocated <
+                                  d->cc->buf_used + m->length) {
+                               d->cc->buf_allocated += 60;
+                               d->cc->buf = xrealloc(d->cc->buf,
+                                                     d->cc->buf_allocated);
+                       }
+                       assert(d->cc->buf_allocated >=
+                              d->cc->buf_used + m->length);
+                       memcpy(d->cc->buf + d->cc->buf_used,
+                              m->msg,
+                              m->length);
+                       d->cc->buf_used += m->length;
+               }
+       }
+}
+
+static void
+process_blkif_fe_message(control_msg_t *m, struct domain *d)
+{
+       switch (m->subtype) {
+       default:
+               warnx("unknown blkif front end message subtype %d",
+                     m->subtype);
+       }
+}
+
+static void
+send_control_message(int type, int subtype, int id,
+                    int size, void *payload, struct domain *target)
+{
+       control_msg_t msg;
+       CONTROL_RING_IDX c;
+
+       msg.type = type;
+       msg.subtype = subtype;
+       msg.id = id;
+       msg.length = size;
+       memcpy(msg.msg, payload, size);
+
+       c = target->ctrl_if->rx_req_prod % CONTROL_RING_SIZE;
+       memcpy(&target->ctrl_if->rx_ring[c], &msg, sizeof(msg));
+       report_work(&target->ctrl_if->rx_req_prod,
+                   target->ctrl_if->rx_req_prod + 1,
+                   target->domid,
+                   0);
+       assert(!target->plugged);
+}
+
+/* Procedure for bringing a new netif front end up:
+
+   -- Front end sends us NETIF_FE_DRIVER_STATUS_CHANGED
+   -- We send back end NETIF_BE_CREATE, wait for a reply
+   -- Back end creates a new netif for us, replies
+   -- We send front end a NETIF_FE_DRIVER_STATUS_CHANGED message saying
+      how many interfaces we've created for it
+   -- We send front end a NETIF_FE_INTERFACE_STATUS_CHANGED for each
+      netif created
+   -- Front end sends us a NETIF_FE_INTERFACE_CONNECT for each netif
+*/
+static void
+handle_netif_fe_driver_status(control_msg_t *m,
+                             netif_fe_driver_status_t *sh,
+                             struct domain *d)
+{
+       netif_fe_interface_status_t if_s;
+       control_msg_t be_msg;
+       netif_be_create_t *be = (void *)be_msg.msg;
+       int r;
+
+       switch (sh->status) {
+       case NETIF_DRIVER_STATUS_UP:
+               /* Tell the back end about the new interface coming
+                * up. */
+               if (d->created_netif_backend) {
+                       send_control_reply(m, d);
+                       send_control_message(CMSG_NETIF_FE,
+                                            CMSG_NETIF_FE_DRIVER_STATUS,
+                                            1,
+                                            sizeof(*sh),
+                                            sh,
+                                            d);
+                       return;
+               }
+               be_msg.type = CMSG_NETIF_BE;
+               be_msg.subtype = CMSG_NETIF_BE_CREATE;
+               be_msg.id = d->domid;
+               be_msg.length = sizeof(*be);
+               be->domid = d->domid;
+               be->netif_handle = 0;
+               memcpy(be->mac, d->netif_mac, 6);
+
+               PRINTF(2,"Telling back end about new front end.\n");
+               pthread_mutex_unlock(&d->mux);
+               send_dom0_message_block(&be_msg);
+               pthread_mutex_lock(&d->mux);
+               PRINTF(3,"Done.\n");
+
+               if (be->status != NETIF_BE_STATUS_OKAY) {
+                       /* Uh oh... can't bring back end
+                        * up. */
+                       send_control_reply(m, d);
+                       send_control_message(CMSG_NETIF_FE,
+                                            CMSG_NETIF_FE_DRIVER_STATUS,
+                                            1,
+                                            sizeof(*sh),
+                                            sh,
+                                            d);
+                       return;
+               }
+               d->created_netif_backend = 1;
+
+               r = our_system(VIFBRIDGE_SCRIPT " up domain=%s mac=%.02x:%.02x:%.02x:%.02x:%.02x:%.02x vif=vif%d.0 bridge=xen-br0",
+                              d->name,
+                              d->netif_mac[0],
+                              d->netif_mac[1],
+                              d->netif_mac[2],
+                              d->netif_mac[3],
+                              d->netif_mac[4],
+                              d->netif_mac[5],
+                              d->domid);
+               if (r != 0)
+                       warn("error %d running " VIFBRIDGE_SCRIPT, r);
+
+               /* Tell domain how many interfaces it has to deal
+                * with. */
+               send_control_reply(m, d);
+               send_control_message(CMSG_NETIF_FE,
+                                    CMSG_NETIF_FE_DRIVER_STATUS,
+                                    1,
+                                    sizeof(*sh),
+                                    sh,
+                                    d);
+
+               PRINTF(2,"Telling front end about its interfaces.\n");
+               if_s.handle = 0;
+               if_s.status = NETIF_INTERFACE_STATUS_DISCONNECTED;
+               send_control_message(CMSG_NETIF_FE,
+                                    CMSG_NETIF_FE_INTERFACE_STATUS,
+                                    1,
+                                    sizeof(if_s),
+                                    &if_s,
+                                    d);
+               PRINTF(3,"Done.\n");
+
+               break;
+       default:
+               warnx("unknown netif status %ld", sh->status);
+               break;
+       }
+}
+
+static void
+handle_netif_fe_interface_connect(control_msg_t *m,
+                                 netif_fe_interface_connect_t *ic,
+                                 struct domain *d)
+{
+       control_msg_t be_msg;
+       netif_be_connect_t *bmsg = (void *)be_msg.msg;
+       netif_fe_interface_status_t fmsg = {0};
+       int evtchn_ports[2];
+       int r;
+
+       PRINTF(4, "front end sent us an interface connect message.\n");
+       send_trivial_control_reply(m, d);
+
+       r = xc_evtchn_bind_interdomain(xc_handle,
+                                      dom0->domid,
+                                      d->domid,
+                                      &evtchn_ports[0],
+                                      &evtchn_ports[1]);
+       if (r < 0)
+               err(1, "allocating network event channel");
+
+       be_msg.type = CMSG_NETIF_BE;
+       be_msg.subtype = CMSG_NETIF_BE_CONNECT;
+       be_msg.id = 0;
+       be_msg.length = sizeof(*bmsg);
+       bmsg->domid = d->domid;
+       bmsg->netif_handle = ic->handle;
+       bmsg->tx_shmem_frame = ic->tx_shmem_frame;
+       bmsg->rx_shmem_frame = ic->rx_shmem_frame;
+       bmsg->evtchn = evtchn_ports[0];
+
+       pthread_mutex_unlock(&d->mux);
+       send_dom0_message_block(&be_msg);
+       pthread_mutex_lock(&d->mux);
+
+       if (bmsg->status != NETIF_BE_STATUS_OKAY) {
+               PRINTF(2, "error connected backend netif: %ld\n",
+                      bmsg->status);
+               abort(); /* Need to handle this */
+       } else {
+               PRINTF(3, "connect backend netif\n");
+
+               /* Tell the domain that we've connected it up. */
+               fmsg.handle = ic->handle;
+               fmsg.status = NETIF_INTERFACE_STATUS_CONNECTED;
+               fmsg.evtchn = evtchn_ports[1];
+               memcpy(fmsg.mac, d->netif_mac, 6);
+
+               send_control_message(CMSG_NETIF_FE,
+                                    CMSG_NETIF_FE_INTERFACE_STATUS,
+                                    0,
+                                    sizeof(fmsg),
+                                    &fmsg,
+                                    d);
+       }
+}
+
+static void
+process_netif_fe_message(control_msg_t *m, struct domain *d)
+{
+       switch (m->subtype) {
+       case CMSG_NETIF_FE_DRIVER_STATUS:
+       {
+               netif_fe_driver_status_t *sh =
+                       (netif_fe_driver_status_t *)m->msg;
+               handle_netif_fe_driver_status(m, sh, d);
+               break;
+       }
+       case CMSG_NETIF_FE_INTERFACE_CONNECT:
+       {
+               netif_fe_interface_connect_t *ic =
+                       (netif_fe_interface_connect_t *)m->msg;
+               handle_netif_fe_interface_connect(m, ic, d);
+               break;
+       }
+       default:
+               warnx("unknown netif front end message subtype %d",
+                     m->subtype);
+       }
+}
+
+static void
+process_control_message(control_msg_t *msg, struct domain *d)
+{
+       control_msg_t m;
+
+       /* Don't want a malicous domain messing us about, so copy the
+          control mesasge into a local buffer. */
+       memcpy(&m, msg, sizeof(m));
+       switch (m.type) {
+       case CMSG_CONSOLE:
+               process_console_control_message(&m, d);
+               break;
+       case CMSG_BLKIF_FE:
+               process_blkif_fe_message(&m, d);
+               break;
+       case CMSG_NETIF_FE:
+               process_netif_fe_message(&m, d);
+               break;
+       default:
+               warnx("unknown control message type %d", m.type);
+       }
+}
+
+static void
+domain_did_control_event(struct domain *d)
+{
+       CONTROL_RING_IDX c;
+
+       /* Pick up and process control ring messages. */
+       while (d->tx_req_cons != d->ctrl_if->tx_req_prod) {
+               c = d->tx_req_cons % CONTROL_RING_SIZE;
+               process_control_message(&d->ctrl_if->tx_ring[c], d);
+               d->tx_req_cons++;
+               assert(d->tx_req_cons <= d->ctrl_if->tx_req_prod);
+               PRINTF(5, "req_cons %ld, req_prod %ld.\n",
+                      d->tx_req_cons, d->ctrl_if->tx_req_prod);
+       }
+
+       /* Take any replies off, and discard them. */
+       if (d->rx_resp_cons != d->ctrl_if->rx_resp_prod)
+               PRINTF(1, "discard %ld events\n",
+                      d->ctrl_if->rx_resp_prod -
+                      d->rx_resp_cons);
+       d->rx_resp_cons = d->ctrl_if->rx_resp_prod;
+}
+
+/* This is the main function for domain control threads */
+void *
+domain_thread_func(void *D)
+{
+       struct domain *d = D;
+       int r;
+       CONTROL_RING_IDX old_resp_prod, old_req_prod;
+
+       pthread_mutex_lock(&d->mux);
+       for (;;) {
+               pthread_cond_wait(&d->cond, &d->mux);
+
+               old_resp_prod = d->ctrl_if->tx_resp_prod;
+               old_req_prod = d->ctrl_if->rx_req_prod;
+
+               domain_did_control_event(d);
+               if (d->cc && d->cc->in_buf_used != 0 && d->plugged == 0) {
+                       r = d->cc->in_buf_used;
+                       if (r > 60)
+                               r = 60;
+                       PRINTF(1, "Sending to domain: %.*s\n",
+                              r, d->cc->in_buf);
+                       send_control_message(CMSG_CONSOLE,
+                                            CMSG_CONSOLE_DATA,
+                                            0,
+                                            r,
+                                            d->cc->in_buf,
+                                            d);
+                       memmove(d->cc->in_buf, d->cc->in_buf + r,
+                               d->cc->in_buf_used - r);
+                       d->cc->in_buf_used -= r;
+               }
+
+               if (d->ctrl_if->tx_resp_prod != old_resp_prod ||
+                   d->ctrl_if->rx_req_prod != old_req_prod)
+                       xc_evtchn_send(xc_handle, d->control_evtchn);
+       }
+}
+
+/* This is the only thing you can do with a domain structure if you're
+   not in the thread which controls that domain.  Domain 0 is
+   special. */
+void
+signal_domain(struct domain *d)
+{
+       CONTROL_RING_IDX c;
+       int id;
+       struct event_receiver *evt;
+
+       pthread_mutex_lock(&d->mux);
+       if (d == dom0) {
+               /* Take events off of dom0's control ring, and send
+                  them to the event receivers. */
+               while (d->tx_req_cons != d->ctrl_if->tx_req_prod) {
+                       c = d->tx_req_cons % CONTROL_RING_SIZE;
+                       id = d->ctrl_if->tx_ring[c].id;
+                       evt = find_event_receiver(id);
+                       if (evt != NULL) {
+                               PRINTF(1, "delivering event id %d\n", evt->id);
+                               pthread_cond_broadcast(&evt->cond);
+                               pthread_mutex_unlock(&d->mux);
+                               sched_yield();
+                               pthread_mutex_lock(&d->mux);
+                       } else {
+                               warnx("unexpected message id %d discarded",
+                                     id);
+                               d->tx_req_cons++;
+                       }
+               }
+               while (d->rx_resp_cons != d->ctrl_if->rx_resp_prod) {
+                       c = d->rx_resp_cons % CONTROL_RING_SIZE;
+                       id = d->ctrl_if->rx_ring[c].id;
+                       evt = find_event_receiver(id);
+                       if (evt != NULL) {
+                               PRINTF(1, "delivering event rep id %d\n", evt->id);
+                               pthread_cond_broadcast(&evt->cond);
+                               pthread_mutex_unlock(&d->mux);
+                               sched_yield();
+                               pthread_mutex_lock(&d->mux);
+                       } else {
+                               warnx("unexpected message reply id %d discarded",
+                                     id);
+                               d->rx_resp_cons++;
+                       }
+               }
+       } else {
+               if (d->plugged) {
+                       d->event_pending = 1;
+               } else {
+                       pthread_cond_broadcast(&d->cond);
+               }
+       }
+       pthread_mutex_unlock(&d->mux);
+}
+
+static void
+handle_evtchn_event(void)
+{
+       short port;
+       struct domain *d;
+
+       read(evtchn_fd, &port, sizeof(short));
+       write(evtchn_fd, &port, sizeof(short));
+       foreach_domain (d) {
+               if (d->control_evtchn == port) {
+                       signal_domain(d);
+                       return;
+               }
+       }
+       warnx("got an event on an unknown port %d", port);
+}
+
+void *
+map_domain_mem(struct domain *d, unsigned long mfn)
+{
+       return xc_map_foreign_range(xc_handle, d->domid,
+                                   PAGE_SIZE, PROT_READ | PROT_WRITE,
+                                   mfn);
+}
+
+static void
+handle_console_event(struct console_connection *cc)
+{
+       int r;
+       int fd;
+
+       switch (cc->state) {
+       case CC_STATE_ERROR:
+               /* Errors shouldn't get here. */
+               abort();
+       case CC_STATE_PENDING:
+               fd = accept(cc->fd, NULL, NULL);
+               if (fd >= 0) {
+                       PRINTF(3, "Accepted console connection for domain %d",
+                              cc->dom->domid);
+                       close(cc->fd);
+                       cc->fd = fd;
+                       cc->state = CC_STATE_CONNECTED;
+                       while (cc->buf_used != 0) {
+                               r = write(cc->fd,
+                                         cc->buf,
+                                         cc->buf_used);
+                               if (r <= 0) {
+                                       cc->state = CC_STATE_ERROR;
+                                       break;
+                               }
+                               memmove(cc->buf,
+                                       cc->buf + r,
+                                       cc->buf_used - r);
+                               cc->buf_used -= r;
+                       }
+                       free(cc->buf);
+                       cc->buf = NULL;
+                       cc->buf_allocated = 0;
+               } else {
+                       PRINTF(1, "error %s accepting console", strerror(errno));
+               }
+               pthread_mutex_unlock(&cc->dom->mux);
+               break;
+       case CC_STATE_CONNECTED:
+               if (cc->in_buf_allocated == 0) {
+                       assert(cc->in_buf_used == 0);
+                       cc->in_buf_allocated = 128;
+                       cc->in_buf = xmalloc(cc->in_buf_allocated);
+               }
+               if (cc->in_buf_used == cc->in_buf_allocated) {
+                       cc->in_buf_allocated *= 2;
+                       cc->in_buf = xrealloc(cc->in_buf, cc->in_buf_allocated);
+               }
+               r = read(cc->fd, cc->in_buf + cc->in_buf_used,
+                        cc->in_buf_allocated - cc->in_buf_used);
+               if (r <= 0) {
+                       cc->state = CC_STATE_ERROR;
+               } else {
+                       cc->in_buf_used += r;
+               }
+               pthread_mutex_unlock(&cc->dom->mux);
+               signal_domain(cc->dom);
+               break;
+       }
+}
+
+static void
+handle_connection_event(struct open_connection *oc)
+{
+       int r;
+
+       /* We know that some amount of data is ready and waiting for
+          us.  Slurp it in. */
+       if (oc->buf_used == oc->buf_allocated) {
+               oc->buf_allocated *= 2;
+               oc->buf = xrealloc(oc->buf, oc->buf_allocated);
+       }
+       r = read(oc->fd, oc->buf + oc->buf_used,
+                oc->buf_allocated - oc->buf_used);
+       if (r < 0) {
+               warn("reading command from remote");
+               oc->state = OC_STATE_ERROR;
+       } else if (r == 0) {
+               warnx("reading command from remote");
+               oc->state = OC_STATE_ERROR;
+       } else {
+               oc->buf_used += r;
+               if (strchr(oc->buf, '\n'))
+                       oc->state = OC_STATE_COMMAND_PENDING;
+       }
+}
+
+static void
+get_and_process_event(void)
+{
+       fd_set read_fds, except_fds;
+       struct open_connection *oc;
+       struct console_connection *cc;
+       int max_fd = listen_fd;
+       int r;
+       struct list_head *li, *temp_li;
+
+       FD_ZERO(&read_fds);
+       FD_ZERO(&except_fds);
+       FD_SET(listen_fd, &read_fds);
+       FD_SET(evtchn_fd, &read_fds);
+       if (evtchn_fd > max_fd)
+               max_fd = evtchn_fd;
+       foreach_open_connection(oc) {
+               FD_SET(oc->fd, &read_fds);
+               FD_SET(oc->fd, &except_fds);
+               if (oc->fd > max_fd)
+                       max_fd = oc->fd;
+       }
+       foreach_console_connection(cc) {
+               FD_SET(cc->fd, &read_fds);
+               FD_SET(cc->fd, &except_fds);
+               if (cc->fd > max_fd)
+                       max_fd = cc->fd;
+       }
+
+       r = select(max_fd + 1, &read_fds, NULL, &except_fds, NULL);
+       if (r < 0)
+               err(1, "select");
+       if (FD_ISSET(listen_fd, &read_fds)) {
+               accept_new_connection();
+       } else if (FD_ISSET(evtchn_fd, &read_fds))
+               handle_evtchn_event();
+
+
+       foreach_open_connection(oc) {
+               if (FD_ISSET(oc->fd, &read_fds))
+                       handle_connection_event(oc);
+               if (FD_ISSET(oc->fd, &except_fds))
+                       oc->state = OC_STATE_ERROR;
+       }
+       list_foreach_safe(&head_console, li, temp_li) {
+               cc = list_item(li, struct console_connection, list);
+               if (FD_ISSET(cc->fd, &read_fds))
+                       handle_console_event(cc);
+               if (FD_ISSET(cc->fd, &except_fds) ||
+                   cc->state == CC_STATE_ERROR) {
+                       PRINTF(1, "Cleaning up console connection");
+                       cc->dom->cc = NULL;
+                       list_remove(&cc->list);
+                       close(cc->fd);
+                       if (cc->buf_allocated != 0)
+                               free(cc->buf);
+                       if (cc->in_buf_allocated != 0)
+                               free(cc->in_buf);
+                       free(cc);
+               }
+       }
+
+       /* Run pending stuff on the open connections. */
+       list_foreach_safe(&head_connection, li, temp_li) {
+               oc = list_item(li, struct open_connection, connection_list);
+               switch (oc->state) {
+               case OC_STATE_ERROR:
+                       list_remove(&oc->connection_list);
+                       closedown_connection(oc);
+                       break;
+               case OC_STATE_COMMAND_PENDING:
+                       process_command(oc);
+                       break;
+               case OC_STATE_CONNECTED:
+                       /* Don't need to do anything */
+                       break;
+               }
+       }
+}
+
+static int
+start_listening(void)
+{
+       int sock;
+       struct sockaddr_in inaddr;
+
+       sock = socket(PF_INET, SOCK_STREAM, 0);
+       if (sock < 0)
+               err(1, "creating socket");
+       memset(&inaddr, 0, sizeof(inaddr));
+       inaddr.sin_family = AF_INET;
+       inaddr.sin_port = htons(MINIXEND_PORT);
+
+       if (bind(sock, (struct sockaddr *)&inaddr, sizeof(inaddr)) < 0)
+               err(1, "binding to port %d", MINIXEND_PORT);
+       if (listen(sock, 5) < 0)
+               err(1, "listening for connections");
+
+       return sock;
+}
+
+static struct domain *
+find_dom0(void)
+{
+       int r;
+       xc_dominfo_t info;
+       struct domain *work;
+
+       r = xc_domain_getinfo(xc_handle, 0, 1, &info);
+       if (r < 0)
+               err(1, "getting domain 0 information");
+       work = xmalloc(sizeof(*work));
+       work->control_evtchn = 2;
+       if (ioctl(evtchn_fd, EVTCHN_BIND, 2) < 0)
+               err(1, "binding to domain 0 control event channel");
+
+       work->domid = 0;
+       work->name = strdup("dom0");
+       work->mem_kb = info.max_memkb;
+       work->state = DOM_STATE_RUNNING;
+       work->shared_info_mfn = info.shared_info_frame;
+
+       work->shared_info = map_domain_mem(work, info.shared_info_frame);
+       work->ctrl_if = (control_if_t *)((unsigned)work->shared_info + 2048);
+       work->tx_req_cons = work->ctrl_if->tx_req_prod;
+       work->rx_resp_cons = work->ctrl_if->rx_resp_prod;
+
+       pthread_mutex_init(&work->mux, NULL);
+       pthread_cond_init(&work->cond, NULL);
+
+       list_insert_after(&work->domain_list, &head_domain);
+
+       return work;
+}
+
+int
+main(int argc, char *argv[])
+{
+       int r;
+
+       r = our_system(NETWORK_SCRIPT " start antispoof=no");
+       if (r < 0)
+               err(1, "running " NETWORK_SCRIPT);
+       if (!WIFEXITED(r)) {
+               if (WIFSIGNALED(r)) {
+                       errx(1, NETWORK_SCRIPT " killed by signal %d",
+                            WTERMSIG(r));
+               }
+               errx(1, NETWORK_SCRIPT " terminated abnormally");
+       }
+       if (WEXITSTATUS(r) != 0)
+               errx(1, NETWORK_SCRIPT " returned error status %d",
+                    WEXITSTATUS(r));
+
+       xc_handle = xc_interface_open();
+
+       listen_fd = start_listening();
+
+       evtchn_fd = open("/dev/xen/evtchn", O_RDWR);
+       if (evtchn_fd < 0)
+               err(1, "openning /dev/xen/evtchn");
+
+       dom0 = find_dom0();
+
+       while (1) {
+               get_and_process_event();
+
+               PRINTF(5, "Dom0 ring state:\n");
+               PRINTF(5, "RX: req_prod %ld, resp_prod %ld, resp_cons %ld\n",
+                      dom0->ctrl_if->rx_req_prod,
+                      dom0->ctrl_if->rx_resp_prod,
+                      dom0->rx_resp_cons);
+               PRINTF(5, "TX: req_prod %ld, resp_prod %ld, req_cons %ld\n",
+                      dom0->ctrl_if->tx_req_prod,
+                      dom0->ctrl_if->tx_resp_prod,
+                      dom0->tx_req_cons);
+       }
+
+       return 0;
+}
+
index 1dc4cee9f48b75ae01a982325a36cd22c416fc71..db28d48529da6fb4b708e1d6d22ce5b3ea31ca5f 100644 (file)
@@ -3,70 +3,6 @@
 
 #include <sys/types.h>
 #include <xc.h>
-#include "domain_controller.h"
-
-/* Yet again, persuading Xen headers to include successfully in a
-   userspace process proves to be beyond me.  Sigh. */
-#define MAX_VIRT_CPUS 1
-
-typedef struct {
-    u32  tsc_bits;      /* 0: 32 bits read from the CPU's TSC. */
-    u32  tsc_bitshift;  /* 4: 'tsc_bits' uses N:N+31 of TSC.   */
-} PACKED tsc_timestamp_t; /* 8 bytes */
-
-typedef struct {
-    u64 mfn_to_pfn_start;      /* MFN of start of m2p table */
-    u64 pfn_to_mfn_frame_list; /* MFN of a table of MFNs that 
-                                 make up p2m table */
-} PACKED arch_shared_info_t;
-
-typedef struct
-{
-    unsigned long ebx;
-    unsigned long ecx;
-    unsigned long edx;
-    unsigned long esi;
-    unsigned long edi;
-    unsigned long ebp;
-    unsigned long eax;
-    unsigned long ds;
-    unsigned long es;
-    unsigned long fs;
-    unsigned long gs;
-    unsigned long _unused;
-    unsigned long eip;
-    unsigned long cs;
-    unsigned long eflags;
-    unsigned long esp;
-    unsigned long ss;
-} PACKED execution_context_t;
-
-typedef struct shared_info_st
-{
-    struct {
-        u8 evtchn_upcall_pending;
-        u8 evtchn_upcall_mask;
-        u8 pad0, pad1;
-    } PACKED vcpu_data[MAX_VIRT_CPUS];  /*   0 */
-    u32 evtchn_pending[32];             /*   4 */
-    u32 evtchn_pending_sel;             /* 132 */
-    u32 evtchn_mask[32];                /* 136 */
-    u64                cpu_freq;        /* 264: CPU frequency (Hz).          */
-    u32                time_version1;   /* 272 */
-    u32                time_version2;   /* 276 */
-    tsc_timestamp_t    tsc_timestamp;   /* TSC at last update of time vals.  */
-    u64                system_time;     /* Time, in nanosecs, since boot.    */
-    u32                wc_sec;          /* Secs  00:00:00 UTC, Jan 1, 1970.  */
-    u32                wc_usec;         /* Usecs 00:00:00 UTC, Jan 1, 1970.  */
-    u64                domain_time;     /* Domain virtual time, in nanosecs. */
-    u64                wall_timeout;    /* 312 */
-    u64                domain_timeout;  /* 320 */
-    execution_context_t execution_context; /* 328 */
-    arch_shared_info_t arch;
-} PACKED shared_info_t;
-
-/* End of stuff which belongs in a Xen header */
-
 
 struct list_head {
        struct list_head *next, **pprev;